package com.zeyu.framework.core.persistence.entity;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.collect.Maps;
import com.zeyu.framework.core.common.Constant;
import com.zeyu.framework.core.persistence.Page;
import com.zeyu.framework.modules.sys.entity.User;
import com.zeyu.framework.modules.sys.utils.UserUtils;
import com.zeyu.framework.utils.StringUtils;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import javax.persistence.Transient;
import javax.xml.bind.annotation.XmlTransient;
import java.io.Serializable;
import java.util.Map;

/**
 * Entity支持类
 */
public abstract class BaseEntity<T> implements Serializable, Constant {

    // ================================================================
    // Constants
    // ================================================================

    /**
     * UID
     */
    private static final long serialVersionUID = 1L;

    /**
     * 删除标记（0：正常；1：删除；2：审核；）
     */
    public static final String DEL_FLAG_NORMAL = "0";
    public static final String DEL_FLAG_DELETE = "1";
    public static final String DEL_FLAG_AUDIT = "2";

    /**
     * 锁定标记（0：固定；1：不固定；）
     */
    public static final int FIX_FLAG_NO = 0;
    public static final int FIX_FLAG_YES = 1;

    /**
     * 根节点, 默认 "1"
     */
    public static final String DEFAULT_ROOT_ID = "1";

    // ================================================================
    // Fields
    // ================================================================

    // 为配合自动增删改查Mapper,这些字段加入 @Transient
    /**
     * 实体编号（唯一标识）
     */
    @Transient
    protected String id;

    /**
     * 当前用户
     */
    @Transient
    protected User currentUser;

    /**
     * 当前实体分页对象
     */
    @Transient
    protected Page<T> page;

    /**
     * 自定义SQL（SQL标识，SQL内容）
     */
    @Transient
    protected Map<String, String> sqlMap;

    /**
     * <pre>
     * 是否是新记录（默认：false），调用setIsNewRecord()设置新记录，使用自定义ID。
     * 设置为true后强制执行插入语句，ID不会自动生成，需从手动传入。
     * </pre>
     */
    @Transient
    protected boolean isNewRecord = false;

    // ================================================================
    // Constructors
    // ================================================================

    /**
     */
    public BaseEntity() {

    }

    /**
     */
    public BaseEntity(String id) {
        this();
        this.id = id;
    }

    // ================================================================
    // Methods from/for super Interfaces or SuperClass
    // ================================================================

    @Override
    public boolean equals(Object obj) {
        if (null == obj) {
            return false;
        }
        if (this == obj) {
            return true;
        }
        if (!getClass().equals(obj.getClass())) {
            return false;
        }
        BaseEntity<?> that = (BaseEntity<?>) obj;
        return null != this.getId() && this.getId().equals(that.getId());
    }

    @Override
    public int hashCode() {
        return HashCodeBuilder.reflectionHashCode(this, false);
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
    }

    // ================================================================
    // Public or Protected Methods
    // ================================================================

    /**
     * 插入之前执行方法，子类实现
     */
    public abstract void preInsert();

    /**
     * 更新之前执行方法，子类实现
     */
    public abstract void preUpdate();

    // ================================================================
    // Getter & Setter
    // ================================================================

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @JsonIgnore
    @XmlTransient
    public User getCurrentUser() {
        if (currentUser == null) {
            currentUser = UserUtils.getUser();
        }
        return currentUser;
    }

    public void setCurrentUser(User currentUser) {
        this.currentUser = currentUser;
    }

    @JsonIgnore
    @XmlTransient
    public Page<T> getPage() {
        if (page == null) {
            page = new Page<>();
        }
        return page;
    }

    public Page<T> setPage(Page<T> page) {
        this.page = page;
        return page;
    }

    @JsonIgnore
    @XmlTransient
    public Map<String, String> getSqlMap() {
        if (sqlMap == null) {
            sqlMap = Maps.newHashMap();
        }
        return sqlMap;
    }

    public void setSqlMap(Map<String, String> sqlMap) {
        this.sqlMap = sqlMap;
    }

    /**
     * 是否是新记录（默认：false），
     * 调用setIsNewRecord()设置新记录，使用自定义ID。 设置为true后强制执行插入语句，ID不会自动生成，需从手动传入。
     *
     * @return 新记录
     */
    public boolean getIsNewRecord() {
        return isNewRecord || StringUtils.isBlank(getId());
    }

    /**
     * 是否是新记录（默认：false），
     * 调用setIsNewRecord()设置新记录，使用自定义ID。 设置为true后强制执行插入语句，ID不会自动生成，需从手动传入。
     */
    public void setIsNewRecord(boolean isNewRecord) {
        this.isNewRecord = isNewRecord;
    }

    // ================================================================
    // Private Methods
    // ================================================================

    // ================================================================
    // Inner or Anonymous Class
    // ================================================================

    // ================================================================
    // Test Methods
    // ================================================================
}
